import os
import re
from pathlib import Path
from typing import Any


class FileService:
    DEFAULT_DATA_FOLDER = "src/backend/data"

    def __init__(self):
        current_directory = Path(Path.cwd())
        data_folder = Path(self.DEFAULT_DATA_FOLDER)

        self.folder_path = current_directory.joinpath(data_folder)

    def create_file_folder(self):
        self.folder_path.mkdir(exist_ok=True)

    def generate_new_filepath(self, file_path: Path) -> Path:
        """
        Generate a new file path. The path is generated by concatenating the base name with a counter index.

        Args:
            file_path (Path): File path.

        Returns:
            Path: New file path.
        """
        base = file_path.stem
        suffix = file_path.suffix

        # Matches for existing counter index
        # For example: x(2).pdf should generate x(3).pdf, and so on
        match = re.match(r"(.+)\((\d+)\)$", base)
        if match:
            base, counter = match.groups()
            counter = int(counter) + 1
        else:
            counter = 1

        new_file_path = file_path.with_name(f"{base}({counter}){suffix}")

        # Recursively handles next generation step if needed
        while new_file_path.exists():
            new_file_path = self.generate_new_filepath(new_file_path)

        return new_file_path

    def upload_file(self, file: Any) -> Path:
        """
        Upload a file to the data folder.

        Args:
            file (Any): File to be uploaded.

        Returns:
            Path: File path.
        """
        # Check if folder already exists
        if not self.folder_path.is_dir():
            self.create_file_folder()

        # Check if file exists
        file_path = self.folder_path.joinpath(file.filename)
        if file_path.exists():
            file_path = self.generate_new_filepath(file_path)

        # Write file to data folder
        with file_path.open("wb") as buffer:
            buffer.write(file.file.read())

        return file_path

    def delete_file(self, file_name: str) -> bool:
        """
        Delete a file in the data folder.

        Args:
            file_path (Any): File to be deleted.

        Returns:
            str: File path.
        """
        # Check if file exists
        file_path = self.folder_path.joinpath(file_name)
        if not file_path.exists():
            return True

        try:
            os.remove(file_path)
            return True
        except OSError:
            print(f"Error deleting file at: {file_path}")
        finally:
            return False
